const { Service } = require('egg');
const { tableToList, zc } = require('../utils/tools');


/**
 * * 班级课表单元格数据处理
 * @param {string[][]} list *
 * @return {Array<string>} *
 */
function dealClass(list) {
  try {
    const need = [];
    for (const i of list) {
      if (i[0].includes('体育')) break; // 体育信息不确定不进行统计
      const reg = /\(([^)]*)\)[^(]*$/; // 匹配字符串中最后一个括号及其内容
      const N = i[0];
      const W = reg.exec(i[1])[1];
      const T = i[1].replace(W, '').replace('()', '');
      const P = zc(W);
      const R = i[2] || '';
      need.push({ N, T, W, P, R });
    }
    /* 合并名称和上课地点相同，上课周次不同的课程 */
    if (need.length > 1) {
      const sub = [];
      for (let i = 0; i < need.length - 1; i++) {
        for (let j = i + 1; j < need.length; j++) {
          if (need[i].N === need[j].N && need[i].R === need[j].R) {
            need[i].W = need[i].W.replace('周', '') + ',' + need[j].W;
            need[i].P = need[i].P.concat(need[j].P);
            sub.push(j);
          }
        }
      }
      for (const i of sub) {
        need.splice(i, 1);
      }
    }
    return need;
  } catch (err) { throw err; }
}


/**
 * 教师课表单元格数据处理
 * @param {string[][]} list *
 * @return {Array<string>} *
 */
function dealTeacher(list) {
  try {
    const need = [];
    const sign = [];
    for (const i of list) {
      const reg = /\(\d.*周\)/;
      const W = i[1].match(reg)[0].replace('(', '').replace(')', '');
      need.push({
        N: i[0],
        C: i[1].replace(W, '').replace('()', ''),
        W,
        P: zc(W),
        R: i[2] || '',
      });
    }
    /* 课程、上课地点、上课班级都相同，但周次不同，将周次合并*/
    if (need.length > 1) {
      const sub = [];
      for (let i = 0; i < need.length - 1; i++) {
        if (sub.indexOf(i) !== -1) continue;
        for (let j = i + 1; j < need.length; j++) {
          if (need[i].N === need[j].N &&
            need[i].R === need[j].R && need[i].C === need[j].C) {
            need[i].W = need[i].W.replace('周', '') + ',' + need[j].W;
            need[i].P = need[i].P.concat(need[j].P);
            sub.push(j);
          }
        }
      }
      need.forEach((e, i) => {
        if (sub.indexOf(i) === -1) sign.push(e);
      });
      return sign;
    }
    return need;
  } catch (err) { throw err; }
}


/**
 * 教室课表单元格数据处理
 * @param {string[][]} list *
 * @return {Array<string>} *
 */
function dealClassroom(list) {
  const sign = [];
  const need = [];
  for (const i of list) {
    const reg = /\(\d.*周\)/;
    const W = i[1].match(reg)[0].replace('(', '').replace(')', '');
    need.push({
      N: i[0],
      T: i[1].replace(W, '').replace('()', ''),
      C: i[2],
      W,
      P: zc(W),
    });
  }
  /* 解决两个问题
      1. 课程名称、上课地点、老师都相同，但周次不同，将周次合并
      2. 大学体育里面同一时间段中一个上课地点，多个老师授课不同班级，将老师合并
   */
  if (need.length > 1) {
    const sub = [];
    for (let i = 0; i < need.length - 1; i++) {
      if (sub.indexOf(i) !== -1) { continue; }
      for (let j = i + 1; j < need.length; j++) {
        // 1
        if (need[i].N === need[j].N &&
          need[i].C === need[j].C && need[i].T === need[j].T) {
          need[i].W = need[i].W.replace('周', '') + ',' + need[j].W;
          need[i].P = need[i].P.concat(need[j].P);
          sub.push(j);
        }
        // 2
        else if (need[i].N === need[j].N &&
          need[i].C === need[j].C && need[i].W === need[j].W) {
          need[i].T = need[i].T + ',' + need[j].T;
          sub.push(j);
        }
      }
    }
    need.forEach((e, i) => {
      if (sub.indexOf(i) === -1) { sign.push(e); }
    });
    return sign;
  }
  return need;
}


// const defaultTime = [ '08:00~09:40', '10:00~11:40', '14:00~15:40', '15:50~17:30', '18:30~20:10', '20:20~22:00' ]; // 记录每节课上课时间
const defaultTime = [
  '08:00~08:45', '08:55~09:40', '10:00~10:45', '10:55~11:40',
  '14:00~14:45', '14:55~15:40', '15:50~16:35', '16:45~17:30',
  '18:30~19:15', '19:25~20:10', '20:20~21:05', '21:15~22:00',
]; // 记录每节课上课时间

const emptyTable = {};
defaultTime.forEach((e, i) => {
  emptyTable[`${i + 1}`] = [[], [], [], [], [], [], []];
});


module.exports = class CourseService extends Service {
  /**
   * * 学生个人课表查询
   * @param {string} term 学期
   * @return {Object} *
   */
  async table(term) {
    const Cookie = this.ctx.state.Cookie;
    const apiUrl = `${this.ctx.state.baseUrl}/jsxsd/xskb/xskb_list.do`;
    const res = await this.ctx.curl(apiUrl, {
      method: 'POST',
      headers: {
        Cookie,
        'Content-Type': 'application/x-www-form-urlencoded',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
      },
      data: {
        cj0701id: '',
        zc: '',
        demo: '',
        xnxq01id: term,
        sfFD: '1',
      },
      timeout: 10000,
    });
    if (res.status === 200) {
      try {
        const cb = (cell, rowIndex, colIndex, $) => {
          const value = cell.text().trim().replace(/\s/g, ''); // 获取单元格内容

          if (rowIndex > 0 && rowIndex <= 6 && colIndex > 0) {
            const tem = [[]];
            cell.find('.kbcontent').each((_, kbcontent) => {
              $(kbcontent).contents().each((_, e) => {
                const value = $(e).text().replace(/\s/g, '');
                if (value === '') return true; // 空白单元格跳过
                else if (value.includes('-----')) tem.push([]); // 分隔线后是另一个课程
                else tem[tem.length - 1].push(value);
              });
            });
            return tem;
          }

          return value;
        };

        const tableList = tableToList(res.data.toString(), '#kbtable', '', cb);
        if (res.data.toString().includes('课表暂未公布')) return { table: emptyTable, defaultTime, note: '课表暂未公布', status: false };

        const note = tableList[tableList.length - 1][1]; // 记录备注信息

        const Ntable = {};
        const period = [ '', '1-2', '3-4', '5-6', '7-8', '9-10', '11-12' ];
        for (let i = 1; i < tableList.length - 1; i++) {
          Ntable[period[i]] = [];

          for (let j = 1; j < tableList[i].length; j++) {
            const infoList = tableList[i][j];
            const tem = infoList.map(item => {
              let [ N, T, W, R ] = '';
              let P = [];
              if (item.length === 0) return '';
              if (item.length === 5) { // 正常情况下有四项
                N = item[0];
                T = item[1];
                W = item[2];
                R = item[4];
                P = zc(item[2]);
              } else if (item.length === 4) { // 课表信息有四项，一般是缺失上课地点
                N = item[0] + item[1];
                T = item[2];
                W = item[3];
                R = '';
                P = zc(item[3]);
              }
              return { N, T, W, R, P };
            }).filter(str => str !== '');
            Ntable[period[i]].push(tem);
          }
        }

        const resultTable = {};
        for (const key in Ntable) {
          resultTable[key.split('-')[0]] = Ntable[key];
          resultTable[key.split('-')[1]] = Ntable[key];
        }
        return { table: resultTable, time: defaultTime, note, status: true };
      }
      catch (err) {
        throw err;
      }
    }
    return { table: emptyTable, time: defaultTime, note: '', status: false };
  }

  /**
   * * 班级课表查询
   * @param {string} term 学期
   * @param {{label:string, value:string}} yx 院系
   * @param {{label:string, value:string}} nj 年级
   * @param {{label:string, value:string}} zy 专业
   * @param {{label:string, value:string}} name 班级
   * @return {object} *
   */
  async Ctable(term, yx, nj, zy, name) {
    const Cookie = this.ctx.state.Cookie;
    const apiUrl = `${this.ctx.state.baseUrl}/jsxsd/kbcx/kbxx_xzb_ifr`;
    const res = await this.ctx.curl(apiUrl, {
      method: 'POST',
      data: {
        xnxqh: term,
        skyx: yx.value,
        sknj: nj.value,
        skzy: zy.value,
        zc1: '',
        zc2: '',
        jc1: '',
        jc2: '',
      },
      headers: {
        Cookie,
        'Content-Type': 'application/x-www-form-urlencoded',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
      },
      timeout: 10000,
    });

    if (res.status === 200) {
      try {
        const cb = (cell, rowIndex, colIndex, $) => {
          const value = cell.text().trim().replace(/\s/g, ''); // 获取单元格内容
          if (rowIndex > 1 && colIndex > 0) {
            if (value === '') return [];
            const item = [];
            $(cell).find('div').each((i, contents) => {
              item.push([]);
              $(contents).contents().each((_, value) => {
                if (value.type === 'text') item[i].push(value.data.replace(/\s/g, ''));
              });
            });
            return dealClass(item);
          }
          return value;
        };
        const tableList = tableToList(res.data.toString(), '#kbtable', '', cb);
        if (tableList.length < 3) return { table: emptyTable, time: defaultTime, note: '' };
        const table = {};
        const row = tableList.filter(e => e[0] === name.label)[0];
        const period = [ '1-2', '3-4', '5-6', '7-8', '9-10', '11-12' ];
        for (let i = 0; i < period.length; i++) {
          table[period[i]] = [];
          for (let j = 0; j < 7; j++) {
            const idx = i + (j * 5) + j + 1;
            table[period[i]].push(row[idx]);
          }
        }
        const resultTable = {};
        for (const key in table) {
          resultTable[key.split('-')[0]] = table[key];
          resultTable[key.split('-')[1]] = table[key];
        }
        return { table: resultTable, time: defaultTime, note: '' };
      } catch (err) {
        throw err;
      }
    }
    return { table: emptyTable, time: defaultTime, note: '' };
  }

  /**
   * * 教师课表查询
   * @param {string} term 学期
   * @param {{label:string, value:string}} yx 院系
   * @param {{label:string, value:string}} name 教师姓名
   * @return {object} *
   */
  async Ttable(term, yx, name) {
    const Cookie = this.ctx.state.Cookie;
    const apiUrl = `${this.ctx.state.baseUrl}/jsxsd/kbcx/kbxx_teacher_ifr`;
    const res = await this.ctx.curl(apiUrl, {
      method: 'POST',
      data: {
        xnxqh: term,
        skyx: yx.value,
        jszc: '',
        zc1: '',
        zc2: '',
        jc1: '',
        jc2: '',
      },
      headers: {
        Cookie,
        'Content-Type': 'application/x-www-form-urlencoded',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
      },
      timeout: 10000,
    });
    if (res.status === 200) {
      try {
        const cb = (cell, rowIndex, colIndex, $) => {
          const value = cell.text().trim().replace(/\s/g, ''); // 获取单元格内容
          if (rowIndex > 1 && colIndex > 0) {
            if (value === '') return [];
            const item = [];
            $(cell).find('div').each((i, contents) => {
              item.push([]);
              $(contents).contents().each((_, value) => {
                if (value.type === 'text') item[i].push(value.data.replace(/\s/g, ''));
              });
            });
            return dealTeacher(item);
          }
          return value;
        };
        const tableList = tableToList(res.data.toString(), '#kbtable', '', cb);
        if (tableList.length < 3) return { table: emptyTable, time: defaultTime, note: '' };
        const row = tableList.filter(e => e[0] === name.label)[0];
        const table = {};
        const period = [ '1-2', '3-4', '5-6', '7-8', '9-10', '11-12' ];
        for (let i = 0; i < period.length; i++) {
          table[period[i]] = [];
          for (let j = 0; j < 7; j++) {
            const idx = i + (j * 5) + j + 1;
            table[period[i]].push(row[idx]);
          }
        }

        const resultTable = {};
        for (const key in table) {
          resultTable[key.split('-')[0]] = table[key];
          resultTable[key.split('-')[1]] = table[key];
        }
        return { table: resultTable, time: defaultTime, note: '' };
      } catch (err) {
        throw err;
      }
    }
    return { table: emptyTable, time: defaultTime, note: '' };
  }

  /**
   * * 教室课表查询
   * @param {string} term 学期
   * @param {{label:string, value:string}} xq 校区
   * @param {{label:string, value:string}} jxl 教学楼
   * @param {{label:string, value:string}} name 教室名称
   * @return {object} *
   */
  async Rtable(term, xq, jxl, name) {
    const Cookie = this.ctx.state.Cookie;
    const apiUrl = `${this.ctx.state.baseUrl}/jsxsd/kbcx/kbxx_classroom_ifr`;
    const res = await this.ctx.curl(apiUrl, {
      method: 'POST',
      data: {
        xnxqh: term,
        skyx: '',
        xqid: xq.value,
        jzwid: jxl.value,
        zc1: '',
        zc2: '',
        jc1: '',
        jc2: '',
      },
      headers: {
        Cookie,
        'Content-Type': 'application/x-www-form-urlencoded',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
      },
      timeout: 10000,
    });
    if (res.status === 200) {
      try {
        const cb = (cell, rowIndex, colIndex, $) => {
          const value = cell.text().trim().replace(/\s/g, ''); // 获取单元格内容
          if (rowIndex > 1 && colIndex > 0) {
            if (value === '') return [];
            const item = [];
            $(cell).find('div').each((i, contents) => {
              item.push([]);
              $(contents).contents().each((_, value) => {
                if (value.type === 'text') item[i].push(value.data.replace(/\s/g, ''));
              });
            });
            return dealClassroom(item);
          }
          return value;
        };
        const tableList = tableToList(res.data.toString(), '#kbtable', '', cb);
        if (tableList.length < 3) return { table: emptyTable, time: defaultTime, note: '' };
        const row = tableList.filter(e => e[0] === name.label)[0];
        const table = {};
        const period = [ '1-2', '3-4', '5-6', '7-8', '9-10', '11-12' ];
        for (let i = 0; i < period.length; i++) {
          table[period[i]] = [];
          for (let j = 0; j < 7; j++) {
            const idx = i + (j * 5) + j + 1;
            table[period[i]].push(row[idx]);
          }
        }

        const resultTable = {};
        for (const key in table) {
          resultTable[key.split('-')[0]] = table[key];
          resultTable[key.split('-')[1]] = table[key];
        }
        return { table: resultTable, time: defaultTime, note: '' };
      } catch (err) {
        throw err;
      }
    }
    return { table: emptyTable, time: defaultTime, note: '' };
  }

};
